﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace XTrace.Viewer
{
	public class DelegateComparer<T> : IComparer<T>, IComparer
	{
		readonly Comparison<T> _comparer;

		public DelegateComparer(Comparison<T> comparer)
		{
			_comparer = comparer;
		}

		public int Compare(T x, T y)
		{
			return _comparer(x, y);
		}

		public int Compare(object x, object y)
		{
			return _comparer((T)x, (T)y);
		}
	}

	public static class SortableObservableCollection
	{
		public static SortableObservableCollection<T, K> New<T, K>(Func<T, K> keySelector)
		{
			return New(keySelector, Comparer<K>.Default);
		}

		public static SortableObservableCollection<T, T> New<T>(IComparer<T> comparer)
		{
			return New<T, T>(x => x, comparer);
		}

		public static SortableObservableCollection<T, T> New<T>(Comparison<T> comparer)
		{
			return New<T, T>(x => x, new DelegateComparer<T>(comparer));
		}

		public static SortableObservableCollection<T, T> New<T>()
		{
			return New<T, T>(x => x, Comparer<T>.Default);
		}

		public static SortableObservableCollection<T, K> New<T, K>(Func<T, K> keySelector, IComparer<K> comparer)
		{
			return new SortableObservableCollection<T, K>(keySelector, comparer);
		}

	}

	public class SortableObservableCollection<T, K> : ObservableCollection<T>
	{
		readonly Func<T, K> _keySelector;
		readonly IComparer<K> _comparer;

		public SortableObservableCollection(Func<T, K> keySelector, IComparer<K> comparer)
		{
			_keySelector = keySelector;
			_comparer = comparer;
		}

		void Sort()
		{
			//if (_keySelector == null)
			{
				InternalSort(Items.OrderBy(_keySelector, _comparer));
			}
//			else
//			{
//				using (P.S("SortableCollection InternalSort2"))
//				{
//					ArrayList.Adapter((IList)Items).Sort((IComparer)_comparer);
//				}
//			}
		}

//		public IDisposable Mute()
//		{
//			_isMuted = true;
//			return new MuteImpl(this);
//		}
//
//		void Unmute()
//		{
//			_isMuted = false;
			// OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
//		}
//
//		bool _isMuted;
//
//		class MuteImpl  :IDisposable
//		{
//			readonly SortableObservableCollection<THandlerClass, K> _col;
//
//			public MuteImpl(SortableObservableCollection<THandlerClass, K> col)
//			{
//				_col = col;
//			}
//
//			public void Dispose()
//			{
//				_col.Unmute();
//			}
//		}

		protected override void InsertItem(int index, T item)
		{
			base.InsertItem(index, item);
			Sort();
		}

		protected override void SetItem(int index, T item)
		{
			base.SetItem(index, item);
			Sort();
		}

		private void InternalSort(IEnumerable<T> sortedItems)
		{
			using (P.S("SortableCollection InternalSort"))
			{
				using (var etor = sortedItems.GetEnumerator())
				{
					for (int index = 0; ; index++)
					{
						using (P.S("SortableCollection.MoveNext"))
						{
							if (!etor.MoveNext()) break;
						}
						var item = etor.Current;
						var currentIndex = IndexOf(item);

#if DEBUG
					if (index > currentIndex)
					{
						throw new Exception();
					}
#endif

						if (index < currentIndex)
						{
							using (P.S("SortableCollection InternalSort.Move"))
							{
								Move(currentIndex, index);
							}
						}
					}
				}
			}
		}
	}
}
